﻿/* 
 *  <copyright file="CGuid.cs" company="Wesley Jowitt">
 *  
 *  SobrietyEngine: Copyright (c) 2011 Wesley Jowitt
 *  
 *  This software is distributed under a software license.
 *   * As of the creation time of this file, the license in use is the Microsoft Permissive License (Ms-PL) 
 *    * The license can be viewed at:
 *     * License.Txt in the root folder of this project
 *      * http://sobrietyengine.codeplex.com/license
 *       * http://www.microsoft.com/opensource/licenses.mspx
 *       
 *  </copyright>
 *   */

using System;
using System.Collections.Generic;

namespace SobrietyEngine.Common
{
    //Generic parser for Token { key value pairs } 
    //used throughout the gameServices. See UDMF format, online.
    /*
     * Token //comment
     * {
     *      key = value;
     *      token
     *      {
     *          key = value;
     *      }
     * }
     * 
     */
    public class StringData
    {
        public String Token { get; set; }
        public String TokenComment { get; set; }
        public Dictionary<String, String> Data { get; set; }
        public List<StringData> SubTokens { get; set; }

        public StringData()
        {
            Data = new Dictionary<string, string>();
            SubTokens = new List<StringData>();
        }

        public override string ToString()
        {
            return "StringData(" + Token + ");";
        }

        //endOfStatementIdentifiers are used to locate strings between symbols
        private static char[] endOfStatementIdentifiers = { '{', '}', ';'};

        //recursively call and fill in string noNewline structure
        public void Read(ref String data, ref int pos)
        {


            while (pos < data.Length)
            {
                //need to determin if we have a token or a kvp.
                int ident = StringDataParser.nextIndexOf(pos, ref data, endOfStatementIdentifiers);

                //if the close braceis closer then any other symbol, we are done.
                if ( ident == -1 || data[ident] == '}')
                {
                    if (ident == -1)
                        pos = data.Length;
                    else
                        pos = ident + 1;
                    break;
                }

                //if the open braceis closer, we have a token and an embedded data object
                if (data[ident] == '{' )
                {
                    //jump to first open brace
                    String token = data.Substring(pos, ident - pos).Trim();
                    StringData nextSD = new StringData();
                    nextSD.Token = token;
                    pos = ident + 1; 
                    nextSD.Read(ref data, ref pos);
                    this.SubTokens.Add(nextSD);
                    
                }
                else //ident char == ;
                {
                    //else we have a KvP
                    String kvpData = data.Substring(pos, ident - pos);
                    String[] split = kvpData.Split('=');
                    String k = split[0].Trim();
                    String v = split[1].Trim();

                    //UDMF format can use strings, defined by open and closing "", so lets see if thats
                    //what we have
                    if (v.Length > 0)
                    {
                        if (v[0] == '"' && v[v.Length - 1] == '"')
                            v = v.Substring(1, v.Length - 2);
                    }

                    this.Data[k] = v;
                    pos = ident + 1;
                }
            }

            return;
        }

        public static StringData ReadData(ref string data)
        {
            StringData sd = new StringData();
            sd.Token = "Root";

            //removes comments from // to end of line
            String strip = StringDataParser.stripComments(ref data, "//");
            //strips out the newlines - not neccessary?
            //strip = StringDataParser.stripNewlines(ref strip);
            //strips out white space - not neccesary?
            //strip = StringDataParser.stripSpaces(ref strip);

            //we should now have a string like this:
            //    token{key=value;key=value;token{}}token{key=value;}
            int pos = 0;
            sd.Read(ref strip, ref pos);

            return sd;
        }
    }
}
